<!DOCTYPE html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="description" content="PragmaticScala">
<meta name="generator" content="Paradox, paradox-material-theme=0.5.1, mkdocs-material=3.0.3">

<meta name="lang:clipboard.copy" content="Copy to clipboard">
<meta name="lang:clipboard.copied" content="Copied to clipboard">
<meta name="lang:search.language" content="">
<meta name="lang:search.pipeline.stopwords" content="true">
<meta name="lang:search.pipeline.trimmer" content="true">
<meta name="lang:search.result.none" content="No matching documents">
<meta name="lang:search.result.one" content="1 matching document">
<meta name="lang:search.result.other" content="# matching documents">
<meta name="lang:search.tokenizer" content="[\s\-]+">


<meta name="description" content="PragmaticScala">
<link rel="shortcut icon" href="../assets/images/favicon.png">
<title>第5章——善用类型 · </title>
<link rel="stylesheet" href="../assets/stylesheets/application.451f80e5.css">
<link rel="stylesheet" href="../lib/material__tabs/dist/mdc.tabs.min.css">
<link rel="stylesheet" href="../lib/prettify/prettify.css">
<script src="../assets/javascripts/modernizr.1aa3b519.js"></script>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700|Roboto+Mono">
<style>
body,input{font-family:"Roboto","Helvetica Neue",Helvetica,Arial,sans-serif}
code,kbd,pre{font-family:"Roboto Mono","Courier New",Courier,monospace}
</style>
<link rel="stylesheet" href="../assets/fonts/font-awesome.css">
<link rel="stylesheet" href="../assets/fonts/material-icons.css">
<link rel="stylesheet" href="../assets/stylesheets/paradox-material-theme.css">
</head>
<body
>
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" data-md-component="overlay" for="__drawer"></label>
<header class="md-header" data-md-component="header">
<nav class="md-header-nav md-grid">
<div class="md-flex">
<div class="md-flex__cell md-flex__cell--shrink">
<a href="../index.html" title="" class="md-header-nav__button md-logo">
<i class="md-icon">local_library</i>
</a>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<label class="md-icon md-icon--menu md-header-nav__button" for="__drawer"></label>
</div>
<div class="md-flex__cell md-flex__cell--stretch">
<div class="md-flex__ellipsis md-header-nav__title" data-md-component="title">
<span class="md-header-nav__topic">
</span>
<span class="md-header-nav__topic">
第5章——善用类型
</span>
</div>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<label class="md-icon md-icon--search md-header-nav__button" for="__search"></label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="query" data-md-state="active">
<label class="md-icon md-search__icon" for="__search"></label>
<button type="reset" class="md-icon md-search__icon" data-md-component="reset" tabindex="-1">&#xE5CD;</button>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" data-md-scrollfix>
<div class="md-search-result" data-md-component="result">
<div class="md-search-result__meta">
Type to start searching
</div>
<ol class="md-search-result__list"></ol>
</div>
</div>
</div>
</div>
</div>

</div>
</div>
</nav>
</header>

<div class="md-container">
<main class="md-main">
<div class="md-main__inner md-grid" data-md-component="container">
<div class="md-sidebar md-sidebar--primary" data-md-component="navigation">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary" data-md-level="0" style="visibility: hidden">
<label class="md-nav__title md-nav__title--site" for="drawer">
<a href="../index.html" title="" class="md-nav__button md-logo">
<span class="md-nav__button md-logo">
<i class="md-icon">local_library</i>
</a>
<a href="../index.html" title="">
</a>
</label>
<ul>
  <li><a href="../contents.html" class="page">目录</a>
  <ul>
    <li><a href="../abstract.html" class="page">内容提要</a></li>
    <li><a href="../part1.html" class="page">第一部分 小试牛刀</a></li>
    <li><a href="../part2.html" class="page">第二部分 深入 Scala</a></li>
    <li><a href="../part3.html" class="page">第三部分 Scala 中的并发编程</a></li>
    <li><a href="../part4.html" class="page">第四部分 Scala 实战</a></li>
    <li><a href="../refs/references.html" class="page">参考书目</a></li>
    <li><a href="../extras.html" class="page">额外指引</a></li>
    <li><a href="../errata.html" class="page">勘误</a></li>
  </ul></li>
</ul>
<nav class="md-nav md-nav--secondary">
<label class="md-nav__title" for="__toc">Table of contents</label>
<ul>
  <li><a href="../chapter-05/index.html#第5章-善用类型" class="header">第5章——善用类型</a>
  <ul>
    <li><a href="../chapter-05/index.html#5-1-类型推断" class="header">5.1 类型推断</a></li>
    <li><a href="../chapter-05/index.html#5-2-基础类型" class="header">5.2 基础类型</a></li>
    <li><a href="../chapter-05/index.html#5-3-返回值类型推断" class="header">5.3 返回值类型推断</a></li>
    <li><a href="../chapter-05/index.html#5-4-参数化类型的型变" class="header">5.4 参数化类型的型变</a></li>
    <li><a href="../chapter-05/index.html#5-5-隐式类型转换" class="header">5.5 隐式类型转换</a></li>
    <li><a href="../chapter-05/index.html#5-6-值类" class="header">5.6 值类</a></li>
    <li><a href="../chapter-05/index.html#5-7-使用隐式转换" class="header">5.7 使用隐式转换</a></li>
  </ul></li>
</ul>
</nav>

</nav>
<ul style="display: none">
<li class="md-nav__item md-version" id="project.version">
<label class="md-nav__link" for="__version">
<i class="md-icon" title="Version">label_outline</i> 1.0.0
</label>
</li>
</ul>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="toc">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary">
<label class="md-nav__title" for="__toc">Table of contents</label>
<ul>
  <li><a href="../chapter-05/index.html#第5章-善用类型" class="header">第5章——善用类型</a>
  <ul>
    <li><a href="../chapter-05/index.html#5-1-类型推断" class="header">5.1 类型推断</a></li>
    <li><a href="../chapter-05/index.html#5-2-基础类型" class="header">5.2 基础类型</a></li>
    <li><a href="../chapter-05/index.html#5-3-返回值类型推断" class="header">5.3 返回值类型推断</a></li>
    <li><a href="../chapter-05/index.html#5-4-参数化类型的型变" class="header">5.4 参数化类型的型变</a></li>
    <li><a href="../chapter-05/index.html#5-5-隐式类型转换" class="header">5.5 隐式类型转换</a></li>
    <li><a href="../chapter-05/index.html#5-6-值类" class="header">5.6 值类</a></li>
    <li><a href="../chapter-05/index.html#5-7-使用隐式转换" class="header">5.7 使用隐式转换</a></li>
  </ul></li>
</ul>
</nav>

</div>
</div>
</div>
<div class="md-content">
<article class="md-content__inner md-typeset">
<div class="md-content__searchable">
<h1><a href="#第5章-善用类型" name="第5章-善用类型" class="anchor"><span class="anchor-link"></span></a>第5章——善用类型</h1>
<p>Scala 的关键优点之一便是 Scala 是静态类型的。通过静态类型，编译器充当了抵御错误 的第一道防线。它们可以验证当前的对象是否就是想要的类型。这是一种在编译时强制接口 约定的方式。这样的验证可以使我们相信，编译后的代码满足我们的预期。</p>
<h2><a href="#5-1-类型推断" name="5-1-类型推断" class="anchor"><span class="anchor-link"></span></a>5.1 类型推断</h2>
<blockquote>
  <p>MakingUseOfTypes/DefiningVariableWithType.scala</p>
</blockquote>
<pre class="prettyprint"><code class="language-scala">val greet: String = &quot;Ahoy!&quot;</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/DefiningVariableWithType.scala#L21">Full source at GitHub</a>
<blockquote>
  <p>MakingUseOfTypes/DefiningVariable.scala</p>
</blockquote>
<pre class="prettyprint"><code class="language-scala">val greet = &quot;Ahoy!&quot;</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/DefiningVariable.scala#L21">Full source at GitHub</a>
<blockquote>
  <p>MakingUseOfTypes/DefiningVariable.scala</p>
</blockquote>
<pre class="prettyprint"><code class="language-scala">println(greet)
println(greet.getClass)</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/DefiningVariable.scala#L25-L26">Full source at GitHub</a>
<p><em>运行结果</em></p>
<pre class="prettyprint"><code class="language-output">Ahoy!
class java.lang.String</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/output/DefiningVariable.output#L2-L3">Full source at GitHub</a>
<blockquote>
  <p>MakingUseOfTypes/TypeInference.scala</p>
</blockquote>
<pre class="prettyprint"><code class="language-scala">class TypeInference {
  val greet = &quot;Ahoy!&quot;
}</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/TypeInference.scala#L20-L22">Full source at GitHub</a>
<p><em>使用命令</em></p>
<pre class="prettyprint"><code class="language-sh">scalac -d bin TypeInference.scala
javap -classpath bin -private TypeInference</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/RunTypeInference.sh#L4-L5">Full source at GitHub</a>
<p><em>反编译结果</em></p>
<pre class="prettyprint"><code class="language-output">Compiled from &quot;TypeInference.scala&quot;
public class TypeInference {
  private final java.lang.String greet;
  public java.lang.String greet();
  public TypeInference();
}</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/shoutput/RunTypeInference.output#L2-L7">Full source at GitHub</a>
<p><em>REPL运行结果</em></p>
<pre class="prettyprint"><code class="language-output">scala&gt; val greet = &quot;Ahoy!&quot;
greet: String = Ahoy!

scala&gt; :quit</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/shoutput/RunREPL.output#L2-L5">Full source at GitHub</a>
<blockquote>
  <p>MakingUseOfTypes/Generics.scala</p>
</blockquote>
<pre class="prettyprint"><code class="language-scala">import java._

var list1: util.List[Int] = new util.ArrayList[Int]
var list2 = new util.ArrayList[Int]</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/Generics.scala#L21-L24">Full source at GitHub</a>
<blockquote>
  <p>MakingUseOfTypes/Generics2.scala</p>
</blockquote>
<pre class="prettyprint"><code class="language-scala">import java._

var list1 = new util.ArrayList[Int]
var list2 = new util.ArrayList
list2.add(???)

list2 = list1 // Compilation Error</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/test/scala/chapter5/Generics2.scala#L21-L27">Full source at GitHub</a>
<p><em>运行结果</em></p>
<pre class="prettyprint"><code class="language-output">Generics2.scala:5: error: type mismatch;
 found   : java.util.ArrayList[Int]
 required: java.util.ArrayList[Nothing]
Note: Int &gt;: Nothing, but Java-defined class ArrayList is invariant in 
type E.
You may wish to investigate a wildcard type such as `_ &gt;: Nothing`. (SLS 
3.2.10)
list2 = list1 // Compilation Error
        ^
one error found</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/output/RunGenerics2.output#L2-L11">Full source at GitHub</a>
<blockquote>
  <p>MakingUseOfTypes/Generics3.scala</p>
</blockquote>
<pre class="prettyprint"><code class="language-scala">import java._

var list1 = new util.ArrayList[Int]
var list2 = new util.ArrayList[Any]

var ref1: Int = 1
var ref2: Any = _

ref2 = ref1 //OK

list2 = list1 // Compilation Error</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/test/scala/chapter5/Generics3.scala#L21-L31">Full source at GitHub</a>
<p><em>运行结果</em></p>
<pre class="prettyprint"><code class="language-output">Generics3.scala:11: error: type mismatch;
 found   : java.util.ArrayList[Int]
 required: java.util.ArrayList[Any]
Note: Int &lt;: Any, but Java-defined class ArrayList is invariant in type E.
You may wish to investigate a wildcard type such as `_ &lt;: Any`. (SLS 
3.2.10)
list2 = list1 // Compilation Error
        ^
one error found</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/output/RunGenerics3.output#L2-L10">Full source at GitHub</a>
<h2><a href="#5-2-基础类型" name="5-2-基础类型" class="anchor"><span class="anchor-link"></span></a>5.2 基础类型</h2>
<blockquote>
  <p>MakingUseOfTypes/ExceptionThrowing.scala</p>
</blockquote>
<pre class="prettyprint"><code class="language-scala">def someOp(number: Int) =
  if (number &lt; 10)
    number * 2
  else
    throw new RuntimeException(&quot;invalid argument&quot;)</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/ExceptionThrowing.scala#L21-L25">Full source at GitHub</a>
<p><em>运行结果</em></p>
<pre class="prettyprint"><code class="language-output">scala&gt; def madMethod() = { throw new IllegalArgumentException() }
madMethod: ()Nothing

scala&gt; :quit</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/shoutput/RunMethodType.output#L2-L5">Full source at GitHub</a>
<blockquote>
  <p>MakingUseOfTypes/OptionExample.scala</p>
</blockquote>
<pre class="prettyprint"><code class="language-scala">def commentOnPractice(input: String) = {
  //rather than returning null
  if (input == &quot;test&quot;) Some(&quot;good&quot;) else None
}

for (input ← Set(&quot;test&quot;, &quot;hack&quot;)) {
  val comment = commentOnPractice(input)
  val commentDisplay = comment.getOrElse(&quot;Found no comments&quot;)
  println(s&quot;input: $input comment: $commentDisplay&quot;)
}</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/OptionExample.scala#L21-L30">Full source at GitHub</a>
<p><em>运行结果</em></p>
<pre class="prettyprint"><code class="language-output">input: test comment: good
input: hack comment: Found no comments</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/output/OptionExample.output#L2-L3">Full source at GitHub</a>
<blockquote>
  <p>MakingUseOfTypes/UsingEither.scala</p>
</blockquote>
<pre class="prettyprint"><code class="language-scala">def compute(input: Int) =
  if (input &gt; 0)
    Right(math.sqrt(input))
  else
    Left(&quot;Error computing, invalid input&quot;)</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/UsingEither.scala#L21-L25">Full source at GitHub</a>
<blockquote>
  <p>MakingUseOfTypes/UsingEither.scala</p>
</blockquote>
<pre class="prettyprint"><code class="language-scala">def displayResult(result: Either[String, Double]): Unit = {
  println(s&quot;Raw: $result&quot;)
  result match {
    case Right(value) ⇒ println(s&quot;result $value&quot;)
    case Left(err)    ⇒ println(s&quot;Error: $err&quot;)
  }
}</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/UsingEither.scala#L29-L35">Full source at GitHub</a>
<blockquote>
  <p>MakingUseOfTypes/UsingEither.scala</p>
</blockquote>
<pre class="prettyprint"><code class="language-scala">displayResult(compute(4))
displayResult(compute(-4))</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/UsingEither.scala#L39-L40">Full source at GitHub</a>
<p><em>运行结果</em></p>
<pre class="prettyprint"><code class="language-output">Raw: Right(2.0)
result 2.0
Raw: Left(Error computing, invalid input)
Error: Error computing, invalid input</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/output/UsingEither.output#L2-L5">Full source at GitHub</a>
<h2><a href="#5-3-返回值类型推断" name="5-3-返回值类型推断" class="anchor"><span class="anchor-link"></span></a>5.3 返回值类型推断</h2>
<blockquote>
  <p>MakingUseOfTypes/Functions.scala</p>
</blockquote>
<pre class="prettyprint"><code class="language-scala">def function1(): Unit = { Math.sqrt(4) }
def function2 = { Math.sqrt(4) }
def function3 = Math.sqrt(4)
def function4: Double = { Math.sqrt(4) }</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/Functions.scala#L21-L24">Full source at GitHub</a>
<p><em>运行结果</em></p>
<pre class="prettyprint"><code class="language-output">scala&gt; def function1 { Math.sqrt(4) }
function1: Unit

scala&gt; def function2 = { Math.sqrt(4) }
function2: Double

scala&gt; def function3 = Math.sqrt(4)
function3: Double

scala&gt; def function4 : Double = { Math.sqrt(4) }
function4: Double

scala&gt; :quit</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/shoutput/RunFunctionReturnTypes.output#L2-L14">Full source at GitHub</a>
<blockquote>
  <p>MakingUseOfTypes/NotAllowed.scala</p>
</blockquote>
<pre class="prettyprint"><code class="language-scala">var arr1 = new Array[Int](3)
var arr2: Array[Any] = _

arr2 = arr1 // Compilation ERROR</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/test/scala/chapter5/NotAllowed.scala#L21-L24">Full source at GitHub</a>
<p><em>运行结果</em></p>
<pre class="prettyprint"><code class="language-output">NotAllowed.scala:4: error: type mismatch;
 found   : Array[Int]
 required: Array[Any]
Note: Int &lt;: Any, but class Array is invariant in type T.
You may wish to investigate a wildcard type such as `_ &lt;: Any`. (SLS 
3.2.10)
arr2 = arr1 // Compilation ERROR
       ^
one error found</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/output/RunNotAllowed.output#L2-L10">Full source at GitHub</a>
<h2><a href="#5-4-参数化类型的型变" name="5-4-参数化类型的型变" class="anchor"><span class="anchor-link"></span></a>5.4 参数化类型的型变</h2>
<blockquote>
  <p>MakingUseOfTypes/Trouble.java</p>
</blockquote>
<pre class="prettyprint"><code class="language-java">//Java code 
class Fruit {} 
class Banana extends Fruit {}
class Apple extends Fruit {}

public class Trouble {
  public static void main(String[] args) {
    Banana[] basketOfBanana = new Banana[2];
    basketOfBanana[0] = new Banana();
    
    Fruit[] basketOfFruits = basketOfBanana; 
    basketOfFruits[1] = new Apple(); 
    
    for(Banana banana : basketOfBanana) {
      System.out.println(banana);
    }    
  }
}</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/Trouble.java#L20-L37">Full source at GitHub</a>
<p><em>运行结果</em></p>
<pre class="prettyprint"><code class="language-output">Exception in thread &quot;main&quot; java.lang.ArrayStoreException: Apple
	at Trouble.main(Trouble.java:12)</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/output/Trouble.output#L2-L3">Full source at GitHub</a>
<blockquote>
  <p>MakingUseOfTypes/OKJava.java</p>
</blockquote>
<pre class="prettyprint"><code class="language-java">//Java code
ArrayList&lt;Integer&gt; list = new ArrayList&lt;Integer&gt;();
ArrayList&lt;Object&gt; list2 = list; // Compilation error</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/test/java/chapter5/OKJava.java#L22-L24">Full source at GitHub</a>
<p><em>绕开限制</em></p>
<pre class="prettyprint"><code class="language-java">ArrayList list3 = list;</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/test/java/chapter5/OKJava.java#L28">Full source at GitHub</a>
<p><em>运行结果</em></p>
<pre class="prettyprint"><code class="language-output">OKJava.java:8: error: incompatible types: ArrayList&lt;Integer&gt; cannot be
converted to ArrayList&lt;Object&gt;
    ArrayList&lt;Object&gt; list2 = list; // Compilation error
                              ^
1 error</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/compileroutput/OKJava.output#L2-L6">Full source at GitHub</a>
<pre class="prettyprint"><code class="language-scala">class Pet(val name: String) {
  override def toString: String = name
}

class Dog(override val name: String) extends Pet(name)

def workWithPets(pets: Array[Pet]): Unit = {}</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/PlayWithPets.scala#L21-L27">Full source at GitHub</a>
<blockquote>
  <p>MakingUseOfTypes/PlayWithPets.scala</p>
</blockquote>
<pre class="prettyprint"><code class="language-scala">val dogs = Array(new Dog(&quot;Rover&quot;), new Dog(&quot;Comet&quot;))</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/PlayWithPets.scala#L31">Full source at GitHub</a>
<blockquote>
  <p>MakingUseOfTypes/PlayWithPets.scala</p>
</blockquote>
<pre class="prettyprint"><code class="language-scala">def playWithPets[T &lt;: Pet](pets: Array[T]): Unit =
  println(&quot;Playing with pets: &quot; + pets.mkString(&quot;, &quot;))</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/PlayWithPets.scala#L37-L38">Full source at GitHub</a>
<blockquote>
  <p>MakingUseOfTypes/PlayWithPets.scala</p>
</blockquote>
<pre class="prettyprint"><code class="language-scala">playWithPets(dogs)</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/PlayWithPets.scala#L42">Full source at GitHub</a>
<p><em>运行结果</em></p>
<pre class="prettyprint"><code class="language-output">Playing with pets: Rover, Comet</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/output/PlayWithPets.output#L2">Full source at GitHub</a>
<blockquote>
  <p>MakingUseOfTypes/PlayWithPets.scala</p>
</blockquote>
<pre class="prettyprint"><code class="language-scala">def copyPets[S, D &gt;: S](fromPets: Array[S], toPets: Array[D]): Unit = { //...
}

val pets = new Array[Pet](10)
copyPets(dogs, pets)</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/PlayWithPets.scala#L46-L50">Full source at GitHub</a>
<blockquote>
  <p>MakingUseOfTypes/MyList.scala</p>
</blockquote>
<pre class="prettyprint"><code class="language-scala">class MyList[+T] //...
var list1 = new MyList[Int]
var list2: MyList[Any] = _
list2 = list1 // OK</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/MyList.scala#L21-L24">Full source at GitHub</a>
<h2><a href="#5-5-隐式类型转换" name="5-5-隐式类型转换" class="anchor"><span class="anchor-link"></span></a>5.5 隐式类型转换</h2>
<blockquote>
  <p>MakingUseOfTypes/DateHelper1.scala</p>
</blockquote>
<pre class="prettyprint"><code class="language-scala">import scala.language.implicitConversions
import java.time.LocalDate

class DateHelper(offset: Int) {
  def days(when: String): LocalDate = {
    val today = LocalDate.now
    when match {
      case &quot;ago&quot;      ⇒ today.minusDays(offset)
      case &quot;from_now&quot; ⇒ today.plusDays(offset)
      case _          ⇒ today
    }
  }
}</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/DateHelper1.scala#L21-L33">Full source at GitHub</a>
<blockquote>
  <p>MakingUseOfTypes/DateHelper1.scala</p>
</blockquote>
<pre class="prettyprint"><code class="language-scala">implicit def convertInt2DateHelper(offset: Int): DateHelper = new DateHelper(offset)

val ago = &quot;ago&quot;
val from_now = &quot;from_now&quot;

val past = 2 days ago
val appointment = 5 days from_now

println(past)
println(appointment)</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/DateHelper1.scala#L37-L46">Full source at GitHub</a>
<p><em>运行结果</em></p>
<pre class="prettyprint"><code class="language-output">2015-08-11
2015-08-18</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/output/DateHelper1.output#L2-L3">Full source at GitHub</a>
<blockquote>
  <p>MakingUseOfTypes/DateHelper.scala</p>
</blockquote>
<pre class="prettyprint"><code class="language-scala">import scala.language.implicitConversions
import java.time.LocalDate

class DateHelper(offset: Int) {
  def days(when: String): LocalDate = {
    val today = LocalDate.now
    when match {
      case &quot;ago&quot;      ⇒ today.minusDays(offset)
      case &quot;from_now&quot; ⇒ today.plusDays(offset)
      case _          ⇒ today
    }
  }
}

object DateHelper {
  val ago = &quot;ago&quot;
  val from_now = &quot;from_now&quot;
  implicit def convertInt2DateHelper(offset: Int): DateHelper = new DateHelper(offset)
}</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/DateHelper.scala#L20-L38">Full source at GitHub</a>
<blockquote>
  <p>MakingUseOfTypes/DaysDSL.scala</p>
</blockquote>
<pre class="prettyprint"><code class="language-scala">import DateHelper._

object DaysDSL extends App {
  val past = 2 days ago
  val appointment = 5 days from_now

  println(past)
  println(appointment)
}</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/DaysDSL.scala#L20-L28">Full source at GitHub</a>
<p><em>运行结果</em></p>
<pre class="prettyprint"><code class="language-output">2015-08-11
2015-08-18</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/shoutput/RunDaysDSL.output#L2-L3">Full source at GitHub</a>
<blockquote>
  <p>MakingUseOfTypes/DateUtil.scala</p>
</blockquote>
<pre class="prettyprint"><code class="language-scala">object DateUtil {
  val ago = &quot;ago&quot;
  val from_now = &quot;from_now&quot;

  implicit class DateHelper(val offset: Int) {
    import java.time.LocalDate
    def days(when: String): LocalDate = {
      val today = LocalDate.now
      when match {
        case &quot;ago&quot;      ⇒ today.minusDays(offset)
        case &quot;from_now&quot; ⇒ today.plusDays(offset)
        case _          ⇒ today
      }
    }
  }
}</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/DateUtil.scala#L20-L35">Full source at GitHub</a>
<blockquote>
  <p>MakingUseOfTypes/DateUtil.scala</p>
</blockquote>
<pre class="prettyprint"><code class="language-scala">object UseDateUtil extends App {
  import DateUtil._

  val past = 2 days ago
  val appointment = 5 days from_now

  println(past)
  println(appointment)
}</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/DateUtil.scala#L39-L47">Full source at GitHub</a>
<p><em>运行结果</em></p>
<pre class="prettyprint"><code class="language-output">       5: invokevirtual #73                 // Method
DateUtil$.DateHelper:(I)LDateUtil$DateHelper;
       8: getstatic     #69                 // Field 
DateUtil$.MODULE$:LDateUtil$;
      11: invokevirtual #77                 // Method 
DateUtil$.ago:()Ljava/lang/String;
      14: invokevirtual #83                 // Method 
DateUtil$DateHelper.days:(Ljava/lang/String;)Ljava/time/LocalDate;</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/shoutput/CompileDateUtil.output#L2-L9">Full source at GitHub</a>
<h2><a href="#5-6-值类" name="5-6-值类" class="anchor"><span class="anchor-link"></span></a>5.6 值类</h2>
<blockquote>
  <p>MakingUseOfTypes/ValDateUtil.scala</p>
</blockquote>
<pre class="prettyprint"><code class="language-scala">implicit class DateHelper(val offset: Int) extends AnyVal {</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/ValDateUtil.scala#L25">Full source at GitHub</a>
<p><em>反编译结果</em></p>
<pre class="prettyprint"><code class="language-output">       8: invokevirtual #78                 // Method
DateUtil$.DateHelper:(I)I
      11: getstatic     #74                 // Field 
DateUtil$.MODULE$:LDateUtil$;
      14: invokevirtual #82                 // Method 
DateUtil$.ago:()Ljava/lang/String;
      17: invokevirtual #86                 // Method 
DateUtil$DateHelper$.days$extension:(ILjava/lang/String;)Ljava/time/LocalDate;</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/shoutput/CompileValDateUtil.output#L2-L9">Full source at GitHub</a>
<blockquote>
  <p>MakingUseOfTypes/NameExample.scala</p>
</blockquote>
<pre class="prettyprint"><code class="language-scala">class Name(val value: String) {
  override def toString: String = value
  def length: Int = value.length
}

object UseName extends App {
  def printName(name: Name): Unit = {
    println(name)
  }

  val name = new Name(&quot;Snowy&quot;)
  println(name.length)
  printName(name)
}</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/NameExample.scala#L21-L34">Full source at GitHub</a>
<p><em>反编译结果</em></p>
<pre class="prettyprint"><code class="language-output">       5: ldc           #76                 // String Snowy
       7: invokespecial #79                 // Method 
Name.&quot;&lt;init&gt;&quot;:(Ljava/lang/String;)V
      10: putfield      #71                 // Field name:LName;
      13: getstatic     #64                 // Field 
scala/Predef$.MODULE$:Lscala/Predef$;
      16: aload_0
      17: invokevirtual #81                 // Method name:()LName;
      20: invokevirtual #85                 // Method Name.length:()I
      23: invokestatic  #91                 // Method 
scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer;
      26: invokevirtual #68                 // Method 
scala/Predef$.println:(Ljava/lang/Object;)V
      29: aload_0
      30: aload_0
      31: invokevirtual #81                 // Method name:()LName;
      34: invokevirtual #93                 // Method printName:(LName;)V
      37: return</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/shoutput/CompileNameExample.output#L2-L19">Full source at GitHub</a>
<blockquote>
  <p>MakingUseOfTypes/NameValExample.scala</p>
</blockquote>
<pre class="prettyprint"><code class="language-scala">class Name(val value: String) extends AnyVal {</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/NameValExample.scala#L21">Full source at GitHub</a>
<p><em>反编译结果</em></p>
<pre class="prettyprint"><code class="language-output">       1: ldc           #78                 // String Snowy
       3: putfield      #75                 // Field 
name:Ljava/lang/String;
       6: getstatic     #64                 // Field 
scala/Predef$.MODULE$:Lscala/Predef$;
       9: getstatic     #83                 // Field Name$.MODULE$:LName$;
      12: aload_0
      13: invokevirtual #85                 // Method 
name:()Ljava/lang/String;
      16: invokevirtual #89                 // Method 
Name$.length$extension:(Ljava/lang/String;)I
      19: invokestatic  #95                 // Method 
scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer;
      22: invokevirtual #72                 // Method 
scala/Predef$.println:(Ljava/lang/Object;)V
      25: aload_0
      26: aload_0
      27: invokevirtual #85                 // Method 
name:()Ljava/lang/String;
      30: invokevirtual #97                 // Method 
printName:(Ljava/lang/String;)V
      33: return</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/shoutput/CompileNameValExample.output#L2-L23">Full source at GitHub</a>
<blockquote>
  <p>MakingUseOfTypes/NameVal2Example.scala</p>
</blockquote>
<pre class="prettyprint"><code class="language-scala">val any: Any = name</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/NameVal2Example.scala#L33">Full source at GitHub</a>
<h2><a href="#5-7-使用隐式转换" name="5-7-使用隐式转换" class="anchor"><span class="anchor-link"></span></a>5.7 使用隐式转换</h2>
<blockquote>
  <p>MakingUseOfTypes/Mask.scala</p>
</blockquote>
<pre class="prettyprint"><code class="language-scala">import MyInterpolator._

val ssn = &quot;123-45-6789&quot;
val account = &quot;0246781263&quot;
val balance = 20145.23

println(mask&quot;&quot;&quot;Account: $account
  |Social Security Number: $ssn
  |Balance: $$^$balance
  |Thanks for your business.&quot;&quot;&quot;.stripMargin)</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/Mask.scala#L21-L30">Full source at GitHub</a>
<blockquote>
  <p>MakingUseOfTypes/MyInterpolator.scala</p>
</blockquote>
<pre class="prettyprint"><code class="language-scala">object MyInterpolator {
  implicit class Interpolator(val context: StringContext) extends AnyVal {
    def mask(args: Any*): StringBuilder = {
      val processed = context.parts.zip(args).map { item ⇒
        val (text, expression) = item
        if (text.endsWith(&quot;^&quot;))
          s&quot;${text.split(&#39;^&#39;)(0)}$expression&quot;
        else
          s&quot;$text...${expression.toString takeRight 4}&quot;
      }.mkString

      new StringBuilder(processed).append(context.parts.last)
    }
  }
}</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/MyInterpolator.scala#L20-L34">Full source at GitHub</a>
<p><em>使用命令</em></p>
<pre class="prettyprint"><code class="language-sh">scalac MyInterpolator.scala mask.scala
scala UseInterpolator</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/RunMask.sh#L4-L5">Full source at GitHub</a>
<p><em>运行结果</em></p>
<pre class="prettyprint"><code class="language-output">Account: ...1263
Social Security Number: ...6789
Balance: $20145.23
Thanks for your business.</code></pre><a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/v1.0.0/src/main/scala/chapter5/shoutput/RunMask.output#L2-L5">Full source at GitHub</a>
</div>
<div>
<a href="https://github.com/ReactivePlatform/Pragmatic-Scala.git/tree/master/src/paradox/chapter-05/index.md" title="Edit this page" class="md-source-file md-edit">
Edit this page
</a>
</div>
<div class="print-only">
<span class="md-source-file md-version">
1.0.0
</span>
</div>
</article>
</div>
</div>
</main>
<footer class="md-footer">
<div class="md-footer-nav">
<nav class="md-footer-nav__inner md-grid">
<a href="../chapter-04/index.html" title="第4章——善用对象" class="md-flex md-footer-nav__link md-footer-nav__link--prev" rel="prev">
<div class="md-flex__cell md-flex__cell--shrink">
<i class="md-icon md-icon--arrow-back md-footer-nav__button"></i>
</div>
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
<span class="md-flex__ellipsis">
<span class="md-footer-nav__direction">
Previous
</span>
第4章——善用对象
</span>
</div>
</a>
<a href="../part2.html" title="第二部分 深入 Scala" class="md-flex md-footer-nav__link md-footer-nav__link--next" rel="next">
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
<span class="md-flex__ellipsis">
<span class="md-footer-nav__direction">
Next
</span>
第二部分 深入 Scala
</span>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<i class="md-icon md-icon--arrow-forward md-footer-nav__button"></i>
</div>
</a>
</nav>
</div>
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-footer-copyright">
Powered by
<a href="https://github.com/lightbend/paradox">Paradox</a>
and
<a href="https://jonas.github.io/paradox-material-theme/">Paradox Material Theme</a>

</div>
</div>
</div>
</footer>

</div>
<script src="../assets/javascripts/application.583bbe55.js"></script>
<script src="../assets/javascripts/paradox-material-theme.js"></script>
<script>app.initialize({version:"0.17",url:{base:"../."}})</script>
<script type="text/javascript" src="../lib/prettify/prettify.js"></script>
<script type="text/javascript" src="../lib/prettify/lang-scala.js"></script>
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function(event) {
window.prettyPrint && prettyPrint();
});
</script>
</body>
</html>
